import request from '@/utils/request'
import headerTools from '@/builder/mixins/card-header-tools'
import callback from '@/builder/mixins/callback'

// 什么都不验证，用来在组件的值改变时，自动清空该字段的验证错误消息
const validateNothing = (rule, value, callback) => {
  callback()
}

export default {
  name: 'AdminForm',
  mixins: [headerTools, callback],
  data() {
    return {
      data: {},
      submitting: false,
    }
  },
  props: {
    fields: {
      type: Array,
      default: () => [],
    },
    action: String,
    method: String,
    labelWidth: String,
  },
  watch: {
    fields: {
      handler() {
        this.fillData()
      },
      immediate: true,
    },
  },
  computed: {
    rules() {
      const rules = {}
      if (this.fields) {
        this.fields.forEach((field) => {
          const rule = {
            validator: validateNothing,
            trigger: ['change', 'blur'],
          }
          if (Array.isArray(field.value)) {
            rule.type = 'array'
          }
          rules[field.name] = [rule]

          if (field.required) {
            rules[field.name].push({
              required: true,
              message: '必填。',
              trigger: ['blur', 'change'],
            })
          }
        })
      }
      return rules
    },
  },
  methods: {
    onReset() {
      this.$refs.form.resetFields()
    },
    onSubmit() {
      if (this.submitting) {
        return
      }

      const form = this.$refs.form

      form.validate((valid) => {
        if (valid) {
          const options = {
            url: this.action,
            method: this.method,
            $form: form,
          }

          const method = options.method.toLowerCase()
          if (method === 'get') {
            options.params = this.data
          } else {
            options.data = this.data
          }

          options.$form.clearValidate()

          this.submitting = true
          request(options)
            .then((res) => {
              const data = res.data

              if (!data.status) {
                return Promise.reject()
              }

              data.callback && this.callback(data.callback)

              // 如果有回调,则要等回调执行完,在跳转,不然Content组件销毁,回调执行不完
              this.$nextTick(() => {
                if (data.to) {
                  this.$router.push(data.to)
                } else {
                  this.submitting = false
                }
              })

            })
            .catch(() => {
              this.submitting = false
            })
        }
      })
    },
    fillData() {
      this.fields.forEach((field) => {
        this.$set(this.data, field.name, field.value)
      })
    },
  },
  render(h) {
    const fields = this.fields.map((field) => {
      return h('el-form-item', {
        props: {
          label: field.label,
          prop: field.name,
        },
        style: {
          width: field.width,
        },
      }, [
        h(field.component, {
          props: {
            ...field.props,
            value: this.data[field.name],
          },
          attrs: {
            name: field.name,
          },
          on: {
            input: (value) => {
              this.data[field.name] = value
            },
          },
        }),
      ])
    })

    if (fields.length > 0) {
      fields.push(
        h('el-form-item', [
          h('el-button', {
            props: {
              type: 'primary',
              loading: this.submitting,
            },
            on: {
              click: this.onSubmit,
            },
          }, '提交'),
          h('el-button', {
            on: {
              click: this.onReset,
            },
          }, '重置'),
        ]),
      )
    }

    // 服务器返回响应后的回调组件
    const callback = this.callbackComponent(h)

    return h('el-card', {
      class: {
        'admin-card': true,
      },
    }, [
      this.makeCardHeader(h),
      h('el-form', {
        props: {
          model: this.data,
          rules: this.rules,
          labelWidth: this.labelWidth,
        },
        class: {
          'admin-form': true,
        },
        ref: 'form',
      }, fields),
      callback,
    ])
  },
}
